home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
bbsutil
/
hsrc_117.zip
/
HEADLZSS.C
< prev
next >
Wrap
Text File
|
1990-10-22
|
21KB
|
798 lines
/**************************************************************
lzhuf.c
written by Haruyasu Yoshizaki 1988/11/20
some minor changes 1989/04/06
comments translated by Haruhiko Okumura 1989/04/07
This stuff is pretty much the original article, but
M. Kimes hacked on it in June of 1990
Screwed with everything to work with XBBS msg bases
**************************************************************/
#include "msgg.h"
#include "twindow.h"
#include "keys.h"
#include "headedit.h"
static int pascal Encode (void);
static int pascal Decode (void);
static int pascal GetBit (void);
static int pascal GetByte (void);
static void pascal InitTree (void); /* initialize trees */
static void pascal InsertNode (int r); /* insert to tree */
static void pascal DeleteNode (int p); /* remove from tree */
static void pascal StartHuff (void); /* init tree */
static void pascal EncodeChar (unsigned c);
static void pascal EncodePosition (unsigned c);
static void pascal EncodeEnd (void);
static int pascal DecodeChar (void);
static int pascal DecodePosition (void);
static void pascal Putcode (int l, unsigned c);
static void pascal Lupdate (int c);
static int pascal alloc_stuff (void);
static void pascal free_stuff (void);
/********** LZSS compression **********/
#define N 4096 /* buffer size */
#define F 60 /* lookahead buffer size */
#define THRESHOLD 2
#define NIL N /* leaf of tree */
typedef unsigned char uchar;
static unsigned getbuf;
static uchar getlen;
static unsigned putbuf;
static uchar putlen;
static unsigned int bytesdone, bytestodo;
static int match_position, match_length;
static unsigned char *text_buf;
static int *lson;
static int *rson;
static int *dad;
static char *inbuf;
static char *outbuf;
/************ Miscellaneous *************/
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
extern unsigned int textsize, codesize;
extern struct _xmsg msg;
int pascal Encode () { /* compression */
int i, c, len, r, s, last_match_length;
unsigned int printcount=0;
if(!alloc_stuff()) {
printf("\n\x1b[1CCouldn't allocate encode buffers!\n");
return 0;
}
codesize = bytesdone = textsize = 0;
printf("\x1b[1CCompressing...\n");
StartHuff();
InitTree();
s = 0;
r = N - F;
for (i = s; i < r; i++) {
text_buf[i]=0x20;
}
for (len = 0; len < F; len++) {
c=(int) *inbuf;
if(!c) break;
inbuf++;
bytesdone++;
if(bytesdone>bytestodo) break;
text_buf[r+len]=c;
}
textsize = len;
for (i = 1; i <= F; i++) InsertNode(r - i);
InsertNode(r);
do {
if (match_length > len)
match_length = len;
if (match_length <= THRESHOLD) {
match_length = 1;
EncodeChar(text_buf[r]);
} else {
EncodeChar(255 - THRESHOLD + match_length);
EncodePosition(match_position);
}
last_match_length = match_length;
for (i = 0; i < last_match_length; i++) {
c=(int)*inbuf;
if(!c) break;
inbuf++;
bytesdone++;
if(bytesdone>bytestodo) break;
DeleteNode(s);
text_buf[s] = c;
if (s < F - 1)
text_buf[s + N] = c;
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
InsertNode(r);
}
if ((textsize += i) > printcount) {
printf("\r\x1b[1C%u",textsize);
printcount += 1024;
}
while (i++ < last_match_length) {
DeleteNode(s);
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
if (--len) InsertNode(r);
}
} while (len > 0);
EndIt:
EncodeEnd();
printf("\r\x1b[1C%u bytes -> %u bytes",textsize,codesize);
free_stuff();
return 1;
}
int pascal Decode () { /* recover */
int i, j, k, r, c;
unsigned int count;
unsigned int printcount=0;
codesize=0;
if (textsize<1024) {
printf("\n\x1b[1CTextsize=%u!\n",textsize);
return 0;
}
if(!alloc_stuff()) {
printf("\n\x1b[1CCouldn't allocate decode buffers!\n");
return 0;
}
printf("\x1b[13;2H");
StartHuff();
for (i = 0; i < N - F; i++) text_buf[i]=0x20;
r = N - F;
for (count = 0; count < textsize; ) {
c = DecodeChar();
if (c < 256) {
*outbuf=(char)c;
outbuf++;
text_buf[r++] = c;
r &= (N - 1);
count++;
}
else {
i = (r - DecodePosition() - 1) & (N - 1);
j = c - 255 + THRESHOLD;
for (k = 0; k < j; k++) {
c = text_buf[(i + k) & (N - 1)];
*outbuf=(char)c;
outbuf++;
text_buf[r++] = c;
r &= (N - 1);
count++;
}
}
if (count > printcount) {
printf("\r\x1b[1C%u ", count);
printcount += 1023;
}
}
free_stuff();
printf("\x1b[13;2H ");
/*
if(count>textsize) {
printf("\x1b[1COVERFLOW: count=%u textsize=%u\n",count,textsize);
pause();
}
*/
return 1;
}
static void pascal InitTree (void) { /* initialize trees */
int i;
for (i = N + 1; i <= N + 256; i++) rson[i] = NIL; /* root */
for (i = 0; i < N; i++) dad[i] = NIL; /* node */
}
static void pascal InsertNode (int r) { /* insert to tree */
int i, p, cmp;
unsigned char *key;
unsigned c;
cmp = 1;
key = &text_buf[r];
p = N + 1 + key[0];
rson[r] = lson[r] = NIL;
match_length = 0;
for ( ; ; ) {
if (cmp >= 0) {
if (rson[p] != NIL)
p = rson[p];
else {
rson[p] = r;
dad[r] = p;
return;
}
} else {
if (lson[p] != NIL)
p = lson[p];
else {
lson[p] = r;
dad[r] = p;
return;
}
}
for (i = 1; i < F; i++)
if ((cmp = key[i] - text_buf[p + i]) != 0)
break;
if (i > THRESHOLD) {
if (i > match_length) {
match_position = ((r - p) & (N - 1)) - 1;
if ((match_length = i) >= F)
break;
}
if (i == match_length) {
if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
match_position = c;
}
}
}
}
dad[r] = dad[p];
lson[r] = lson[p];
rson[r] = rson[p];
dad[lson[p]] = r;
dad[rson[p]] = r;
if (rson[dad[p]] == p)
rson[dad[p]] = r;
else
lson[dad[p]] = r;
dad[p] = NIL; /* remove p */
}
static void pascal DeleteNode (int p) /* remove from tree */
{
int q;
if (dad[p] == NIL)
return; /* not registered */
if (rson[p] == NIL)
q = lson[p];
else
if (lson[p] == NIL)
q = rson[p];
else {
q = lson[p];
if (rson[q] != NIL) {
do {
q = rson[q];
} while (rson[q] != NIL);
rson[dad[q]] = lson[q];
dad[lson[q]] = dad[q];
lson[q] = lson[p];
dad[lson[p]] = q;
}
rson[q] = rson[p];
dad[rson[p]] = q;
}
dad[q] = dad[p];
if (rson[dad[p]] == p)
rson[dad[p]] = q;
else
lson[dad[p]] = q;
dad[p] = NIL;
}
/* Huffman coding */
#define N_CHAR (256 - THRESHOLD + F)
/* kinds of characters (character code = 0..N_CHAR-1) */
#define T (N_CHAR * 2 - 1) /* size of table */
#define R (T - 1) /* position of root */
#define MAX_FREQ 0x8000 /* updates tree when the */
/* root frequency comes to this value. */
/* table for encoding and decoding the upper 6 bits of position */
/* for encoding */
uchar p_len[64] = {
0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0